# coding: utf-8

import datetime

from sqlalchemy import text

from app.extensions import db
from app.models import BaseModel, get_timestamp
from app.op.models import User, Follow
from app.relationship.constant import FriendStatus, FRIEND_LIST_KEY, \
    RelationshipState, InviteSource
from common.utils import redis_client


class MobileList(BaseModel):
    """
    create by ld_wu 2018-01-08
    通讯录
    """
    __tablename__ = 'mobile_lists'

    # 通讯录所有人的id
    follower_id = db.Column(
        db.Integer(), db.ForeignKey('user.id'), index=True, nullable=False
    )
    # 通讯录电话
    mobile = db.Column(db.String(32), nullable=False, index=True)
    # 状态（10待认证、20已添加）
    status = db.Column(db.Integer(), default=0)
    # 被添加人
    followed_id = db.Column(db.Integer(), nullable=True)
    # 发送短信时间
    invite_date = db.Column(db.Date())
    nickname = db.Column(
        db.String(128), default='', server_default=text("''")
    )
    # 推荐(添加推荐用户的标识，True表示添加了推荐用户)
    for_recommend = db.Column(db.Boolean(), server_default=text("FALSE"))
    # 邀请人名
    invite_name = db.Column(db.String(32), server_default=text("''"))

    @property
    def source_display(self):
        """
        通讯录中的记录来源
        如果是有邀请人的直接显示邀请人
        否则为通讯录好友
        :return:
        """
        return (
            '{}邀请的'.format(self.invite_name)
            if self.invite_name
            else '通讯录好友'
        )

    @property
    def status_display(self):
        return FriendStatus.mapping.get(self.status, '')

    @classmethod
    def remove_deleted_list(cls, follower_id, mobiles):
        """
        移除从客户通讯录已经删除的号码的未处理的记录
        :return:
        """
        records = cls.query.filter(
            cls.follower_id == follower_id,
            cls.status == FriendStatus.DEFAULT,
            cls.deleted_at == 0,
            cls.for_recommend.is_(False)
        ).all()
        for each in records:
            if each.mobile not in mobiles:
                each.deleted_at = get_timestamp()

    @classmethod
    def insert_mobile_list(cls, follower_id, mobile_list, user_mapping, phones):
        cls.remove_deleted_list(follower_id, phones)
        existed_records = cls.query.filter(
            cls.follower_id == follower_id,
            cls.mobile.in_(phones),
            cls.deleted_at == 0
        ).all()
        user_ids = [each.id for each in user_mapping.values()]
        invite_logs = InviteLog.query.filter(
            InviteLog.followed_id == follower_id,
            InviteLog.follower_id.in_(user_ids)
        ).all()

        status_mapping = {each.follower_id: each.status for each in invite_logs}
        for each in existed_records:
            each.status = status_mapping.get(each.followed_id, each.status)
            if each.for_recommend:
                each.for_recommend = False
        mobile_mapping = {each.mobile: each for each in existed_records}
        insert_phones = set()
        for each in mobile_list:
            mobile = each['mobile']
            if mobile in insert_phones:
                continue
            if mobile not in mobile_mapping:
                user = user_mapping.get(mobile)
                # 写入未注册的
                followed_id = user.id if user else None

                if follower_id == followed_id:
                    continue
                # 获取当前关系的状态
                status = status_mapping.get(
                    followed_id, FriendStatus.DEFAULT
                )
                cls.create(
                    follower_id=follower_id,
                    mobile=mobile,
                    followed_id=followed_id,
                    status=status,
                    nickname=each.get('nickname', '')
                )
            else:
                record = mobile_mapping[mobile]
                record.nickname = each.get('nickname', '')
            insert_phones.add(mobile)

    @classmethod
    def update_mobile(cls, followed_id, mobile):
        """
        create by ld_wu 2018-01-08
        管理后台修改用户电话号码时调用，更新通讯录电话
        :return:
        """
        if followed_id:
            cls.query.filter(
                cls.followed_id == followed_id,
            ).update(
                dict(
                    mobile=mobile
                ),
                synchronize_session='fetch'
            )

    @classmethod
    def update_status(cls, follower_id, followed_id, status):
        """
        邀请好友时，更新通讯录状态
        :return:
        """
        cls.query.filter(
            cls.followed_id == followed_id,
            cls.follower_id == follower_id,
            cls.deleted_at == 0,
            cls.status < status
        ).update(
            dict(status=status),
            synchronize_session='fetch'
        )

    def extend_user_info(self, user_id, user_mapping):
        """
        create by ld_wu 2018-01-08
        :return:
        """

        info = _extend_user_info(self, user_id, user_mapping)
        info['shared_friends_count'] = len(self.shared_friends)
        return info

    @property
    def shared_friends(self):
        """
        共同好友
        :return:
        """
        if self.followed_id:
            follower_key = FRIEND_LIST_KEY.format(user_id=self.follower_id)
            followed_key = FRIEND_LIST_KEY.format(user_id=self.followed_id)
            shared_friend = redis_client.sinter(follower_key, followed_key)
        else:
            shared_friend = list()
        return shared_friend


class InviteLog(BaseModel):
    """
    create by ld_wu 2018-01-08
    添加好友记录
    """

    __tablename__ = 'invite_logs'

    # 添加好友的人
    follower_id = db.Column(
        db.Integer(), db.ForeignKey('user.id'), index=True
    )
    # 被添加人
    followed_id = db.Column(
        db.Integer(), db.ForeignKey('user.id'), index=True
    )
    # 状态（10待认证、20已添加）
    status = db.Column(db.Integer(), default=0)
    # 是否已读的状态
    read_status = db.Column(db.Boolean(), default=False)
    # 添加时间
    invite_time = db.Column(db.DateTime(), default=datetime.datetime.now)

    # 邀请备注（）
    remark = db.Column(db.String(64), default='', server_default=text("''"))

    # 系统添加（即不是个人主动添加好友，只用于显示）
    for_display = db.Column(
        db.Boolean(), default=False, server_default=text("False")
    )
    # 来源
    source = db.Column(db.Integer(), default=0, server_default=text("'0'"))
    # 邀请人名
    invite_name = db.Column(db.String(32), server_default=text("''"))
    # 是否已查看（红点标识）
    # 点击名片后置为False
    red_display = db.Column(db.Boolean(), server_default=text("False"))

    @property
    def status_display(self):
        return FriendStatus.mapping.get(self.status, '')

    @property
    def source_display(self):
        if self.source == InviteSource.SUBORDINATE.value:
            return (
                '{}邀请的'.format(self.invite_name) if self.invite_name else ''
            )
        return InviteSource(self.source).display

    @classmethod
    def invite_logs(cls, user_id):
        """
        create_by ld_wu 2018-01-08
        添加好友记录列表
        1、更新历史状态为已读
        2、获取添加历史
        """
        cls.query.filter(
            cls.followed_id == user_id
        ).update(
            dict(read_status=True)
        )

        return cls.query.filter(
            cls.followed_id == user_id,
            cls.deleted_at == 0
        ).order_by(
            cls.invite_time.desc()
        )

    @classmethod
    def invite_friend(
            cls, follower_id, followed_id, remark='', source=0):
        """
        create by ld_wu 2018-01-11
        """
        if follower_id == followed_id:
            return
        invite_name = ''
        # 写入好友邀请记录
        log = InviteLog.get_by_args(
            follower_id=follower_id,
            followed_id=followed_id
        )

        if not source:
            mobile_list = MobileList.get_by_args(
                follower_id=follower_id,
                followed_id=followed_id
            )
            if mobile_list:
                source = InviteSource.MOBILE_LIST.value
            else:
                source = InviteSource.SEARCH.value

        if not log:
            log = InviteLog.create(
                follower_id=follower_id,
                followed_id=followed_id,
                status=FriendStatus.APPROVAL,
                remark=remark,
                source=source,
                invite_name=invite_name,
                red_display=True
            )
            if remark:
                InviteMessage.create(
                    from_id=follower_id,
                    to_id=followed_id,
                    content=remark
                )
        else:
            log.invite_time = datetime.datetime.now()
            log.remark = remark
            log.status = FriendStatus.APPROVAL
            log.read_status = False
            log.red_display = True
            log.source = log.source or source
            if remark:
                InviteMessage.create(
                    from_id=follower_id,
                    to_id=followed_id,
                    content=remark
                )
        followed_log = InviteLog.get_by_args(
            follower_id=followed_id,
            followed_id=follower_id
        )
        if followed_log:
            # 对方未添加我的
            if followed_log.status != FriendStatus.APPROVAL:
                followed_log.status = FriendStatus.WAITING
        else:
            # 我邀请的相应对方为邀请我的
            if source == InviteSource.MY_INVITE.value:
                source = InviteSource.INVITE_ME.value
            # 用于添加人的显示记录
            InviteLog.create(
                followed_id=follower_id,
                follower_id=followed_id,
                status=FriendStatus.WAITING,
                remark=remark,
                source=source,
                read_status=True
            )
        # 更新他的通讯录中的状态
        MobileList.update_status(
            followed_id, follower_id, FriendStatus.APPROVAL
        )

        # 更新我的通讯录的状态
        MobileList.query.filter(
            MobileList.follower_id == follower_id,
            MobileList.followed_id == followed_id,
            MobileList.status != FriendStatus.APPROVAL
        ).update(
            dict(status=FriendStatus.WAITING),
            synchronize_session='fetch'
        )
        return log

    @classmethod
    def un_read_count(cls, user_id):
        """
        create by ld_wu 2018-01-08
        被加好友，未查看的数量
        """
        return cls.query.filter(
            cls.followed_id == user_id,
            cls.read_status.__eq__(False)
        ).count()

    def extend_user_info(self, user_id, user_mapping):
        """
        create by ld_wu 2018-01-08
        :return:
        """

        return _extend_user_info(self, user_id, user_mapping)

    @classmethod
    def update_status(cls, follower_id, followed_id, status):
        """
        邀请好友时，更新通讯录状态
        :return:
        """
        cls.query.filter(
            cls.followed_id == followed_id,
            cls.follower_id == follower_id,
            cls.deleted_at == 0,
            cls.status <= FriendStatus.WAITING
        ).update(
            dict(status=status),
            synchronize_session='fetch'
        )

    @classmethod
    def update_pass_status(cls, follower_id, followed_id):
        cls.update_status(follower_id, followed_id, FriendStatus.PASS)
        cls.update_status(followed_id, follower_id, FriendStatus.PASS)

    def pass_invite(self):
        # 记录状态修改为已添加

        self.update_pass_status(self.follower_id, self.followed_id)

        # 更新用户通讯录信息
        MobileList.update_status(
            follower_id=self.follower_id,
            followed_id=self.followed_id,
            status=FriendStatus.PASS
        )
        MobileList.update_status(
            followed_id=self.follower_id,
            follower_id=self.followed_id,
            status=FriendStatus.PASS
        )
        follower_key = FRIEND_LIST_KEY.format(user_id=self.follower_id)
        followed_key = FRIEND_LIST_KEY.format(user_id=self.followed_id)

        follower = Follow.get_by_args(
            follower_id=self.follower_id,
            followed_id=self.followed_id
        )

        followed = Follow.get_by_args(
            follower_id=self.followed_id,
            followed_id=self.follower_id
        )

        if not follower:
            user = User.get_by_id(self.follower_id)
            Follow.create(
                follower_id=self.follower_id,
                followed_id=self.followed_id,
                alias=user.nickname,
                has_set_alias=False
            )
        if not followed:
            user = User.get_by_id(self.followed_id)
            Follow.create(
                follower_id=self.followed_id,
                followed_id=self.follower_id,
                alias=user.nickname,
                has_set_alias=False
            )
        # 写入redis
        redis_client.sadd(follower_key, self.followed_id)
        redis_client.sadd(followed_key, self.follower_id)


class InviteMessage(BaseModel):
    """
    create by ld_wu 2018-03-28
    邀请记录的消息记录
    """

    __tablename__ = 'invite_messages'

    # 消息发送人id
    from_id = db.Column(db.Integer(), nullable=False)
    group_id = db.Column(
        db.String(32),
        index=True,
        nullable=False,
        server_default=text("''")
    )
    # 消息内容
    content = db.Column(db.String(64), default='', server_default=text("''"))

    @classmethod
    def create(cls, **kwargs):
        from_id = kwargs['from_id']
        to_id = kwargs.pop('to_id')
        kwargs['group_id'] = '%s:%s' % tuple(
            sorted([str(from_id), str(to_id)])
        )
        return super(cls, cls).create(**kwargs)


def _extend_user_info(self, user_id, user_mapping):
    """
    create by ld_wu 2018-01-08
    :return:
    """

    extend_id = (
        self.follower_id if self.followed_id == user_id else self.followed_id
    )
    friends = Follow.query.filter(
        Follow.followed_id == user_id,
        Follow.has_set_alias.is_(True)
    ).all()

    alias_mapping = {each.follower_id: each.alias for each in friends}
    extend_info = user_mapping.get(extend_id, dict(
        user_id=0,
        com='',
        nickname=getattr(self, 'nickname', ''),
        avatar='',
        phone_area_name=''
    ))
    is_followed = (
        (user_id == self.followed_id)
        if not isinstance(self, InviteLog)
        else
        (user_id == self.followed_id and not getattr(self, 'for_display', False))
    )

    def get_state():
        # 系统添加的直接显示状态
        if isinstance(self, InviteLog):
            return RelationshipState.STATUS_DISPLAY
        # 可邀请
        elif not extend_id and self.status == FriendStatus.DEFAULT:
            return RelationshipState.CAN_INVITE
        # 可加好友
        elif extend_id and self.status == FriendStatus.DEFAULT:
            return RelationshipState.CAN_ADD
        # 直接显示状态
        else:
            return RelationshipState.STATUS_DISPLAY

    log_info = dict(
        follower_id=self.follower_id,
        followed_id=self.followed_id,
        invite_id=self.id,
        mobile=getattr(self, 'mobile', ''),
        status=self.status,
        status_display=self.status_display,
        is_followed=is_followed,
        state=get_state(),
        id=self.id,
        remark=getattr(self, 'remark', ''),
        source=self.source_display,
        alias=alias_mapping.get(extend_id, ''),
        red_display=getattr(self, 'red_display', False)
    )
    log_info.update(extend_info)
    nickname = getattr(self, 'nickname', '')
    if nickname and not is_followed:
        log_info['nickname'] = nickname
    return log_info


class PersonalDynamic(BaseModel):
    """
    create by ld_wu 2018-01-24
    个人动态
    """
    __tablename__ = 'personal_dynamic'

    # 发起人
    user_id = db.Column(db.Integer(), db.ForeignKey('user.id'), index=True)
    # 内容
    content = db.Column(db.String(600), default='')
    # 图片
    pictures = db.Column(db.JSON())
    # 可见范围
    visible_type = db.Column(db.Integer())
    # 可见地区ids
    area_ids = db.Column(db.TEXT())
    # 消费的汇币
    bid_point = db.Column(db.Integer(), server_default=text("'0'"))


class DynamicReply(BaseModel):
    """
    create by ld_wu 2018-01-24
    动态回复
    """
    __tablename__ = 'dynamic_reply'

    # 动态id
    personal_dynamic_id = db.Column(
        db.Integer(), db.ForeignKey('personal_dynamic.id'), index=True
    )
    # 留言人
    user_id = db.Column(db.Integer())
    # 回复人
    reply_to = db.Column(db.Integer())
    # 内容
    content = db.Column(db.String(200), default='')


class DynamicLike(BaseModel):
    """
    create by ld_wu 2018-01-24
    动态点赞
    """
    __tablename__ = 'dynamic_like'

    # 动态id
    personal_dynamic_id = db.Column(
        db.Integer(), db.ForeignKey('personal_dynamic.id'), index=True
    )
    # 点赞人
    user_id = db.Column(db.Integer())
